package lg.minecraft.plugin.cobblemoncore.util;

import com.cobblemon.mod.common.CobblemonEntities;
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity;
import com.cobblemon.mod.common.item.PokemonItem;
import com.cobblemon.mod.common.pokeball.PokeBall;
import com.cobblemon.mod.common.pokemon.Pokemon;
import com.cobblemon.mod.common.pokemon.Species;
import net.minecraft.*;
import net.minecraft.server.level.EntityPlayer;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.craftbukkit.v1_21_R1.CraftServer;
import org.bukkit.craftbukkit.v1_21_R1.CraftWorld;
import org.bukkit.craftbukkit.v1_21_R1.entity.CraftEntity;
import org.bukkit.craftbukkit.v1_21_R1.entity.CraftPlayer;
import org.bukkit.craftbukkit.v1_21_R1.inventory.CraftItemStack;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemFlag;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.jetbrains.annotations.NotNull;

/**
 * @author langle__
 * @version 1.0
 */
public final class BukkitNmsConverter {

    private BukkitNmsConverter() {}

    public static class_2338 toBlockPos(@NotNull Location location) {
        return new class_2338(location.getBlockX(), location.getBlockY(), location.getBlockZ());
    }

    public static class_1937 toWorld(@NotNull World world) {
        return class_1937.class.cast(((CraftWorld) world).getHandle());
    }

    public static class_3222 toPlayer(@NotNull Player player) {
        return class_3222.class.cast(((CraftPlayer) player).getHandle());
    }

    public static Player toPlayer(@NotNull class_3222 player) {
        return EntityPlayer.class.cast(player).getBukkitEntity().getPlayer();
    }

    public static Entity toEntity(@NotNull class_1297 entity) {
        net.minecraft.world.entity.Entity nmsEntity = net.minecraft.world.entity.Entity.class.cast(entity);
        return CraftEntity.getEntity((CraftServer) Bukkit.getServer(), nmsEntity);
    }

    public static class_1297 toEntity(@NotNull Entity entity) {
        return class_1297.class.cast(((CraftEntity) entity).getHandle());
    }

    public static PokemonEntity toPokemonEntity(@NotNull Entity entity) {
        return PokemonEntity.class.cast(((CraftEntity) entity).getHandle());
    }

    public static ItemStack toItemStack(@NotNull class_1799 itemStack) {
        net.minecraft.world.item.ItemStack nmsItem = net.minecraft.world.item.ItemStack.class.cast(itemStack);
        return CraftItemStack.asBukkitCopy(nmsItem);
    }

    public static class_1799 toItemStack(@NotNull ItemStack bukkitItem) {
        net.minecraft.world.item.ItemStack nmsItem = CraftItemStack.asNMSCopy(bukkitItem);
        return class_1799.class.cast(nmsItem);
    }

    public static ItemStack getPokemonItem(@NotNull Pokemon pokemon) {
        class_1799 item = PokemonItem.from(pokemon);
        return toItemStack(item);
    }

    public static ItemStack getPokemonItem(@NotNull Species species) {
        class_1799 item = PokemonItem.from(species);
        return toItemStack(item);
    }

    public static ItemStack getPokeBallItem(PokeBall pokeBall) {
        ItemStack item = toItemStack(pokeBall.stack(1));
        ItemMeta meta = item.getItemMeta();
        if (meta != null) {
            meta.addItemFlags(ItemFlag.values());
            item.setItemMeta(meta);
        }
        return item;
    }

    public static class_5455 getRegistryAccess() {
        World world = Bukkit.getWorlds().getFirst();
        return getRegistryAccess(world);
    }

    public static class_5455 getRegistryAccess(World world) {
        return toWorld(world).method_30349();
    }

    public static PokemonEntity spawnPokemon(@NotNull Pokemon pokemon, @NotNull Location location) {
        World world = location.getWorld();
        if (world == null) throw new IllegalArgumentException("World is null");

        class_1937 level = BukkitNmsConverter.toWorld(world);

        PokemonEntity pokemonEntity = new PokemonEntity(level, pokemon, CobblemonEntities.POKEMON);
        pokemonEntity.method_5814(location.getX(), location.getY(), location.getZ());
        level.method_8649(pokemonEntity);

        return pokemonEntity;
    }

}
